import cv2
import numpy as np
import os
import matplotlib.pyplot as plt

# 读取图像文件
image = cv2.imread('hanzi1.jpg')

# 将图像转换为灰度图
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 对灰度图进行全局阈值处理转化为二值图像，并打印转化后的图像
threshold = 130
_, binary_image = cv2.threshold(gray_image, threshold, 255, cv2.THRESH_BINARY_INV)

# 创建元素结构，采用3*3的矩形元素
kernel = np.ones((3, 3), np.uint8)

# 进行腐蚀操作，迭代3次增强腐蚀效果
eroded_image = cv2.erode(binary_image, kernel, iterations=3)

dilated_image = cv2.dilate(eroded_image, kernel, iterations=2)  # 对图像进行膨胀操作

# 中值滤波去除dilated_image的小白点
median_image = cv2.medianBlur(dilated_image, 13)

# 运用闭运算填充闭合区域
kernel3 = np.ones((7, 7), np.uint8)
closing_image = cv2.morphologyEx(median_image, cv2.MORPH_CROSS, kernel3, iterations=10)

# Canny边缘识别
lower = 50
upper = 200
edges_no_blur = cv2.Canny(closing_image, lower, upper)

img_blur = cv2.GaussianBlur(closing_image, (3, 3), 0)  # 高斯滤波
edges_with_blur = cv2.Canny(img_blur, lower, upper)

# 提取轮廓
contours, _ = cv2.findContours(edges_with_blur, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 计算所有轮廓矩形的平均大小
average_width = 0
average_height = 0
total_contours = len(contours)

for contour in contours:
    x, y, w, h = cv2.boundingRect(contour)
    average_width += w
    average_height += h

average_width /= total_contours
average_height /= total_contours

# 创建字符图像保存目录
chars_dir = 'chars'
if not os.path.exists(chars_dir):
    os.makedirs(chars_dir)

count = 1
for contour in contours:
    # 计算轮廓周长
    perimeter = cv2.arcLength(contour, True)
    
    # 获取轮廓的边界矩形
    x, y, w, h = cv2.boundingRect(contour)

    # 计算长宽比
    aspect_ratio = w / h if h != 0 else 0

    # 如果长宽比接近1:1且周长大于600，则认为可能是汉字
    if abs(aspect_ratio - 1) < 0.3 and perimeter > 600:
        # 检查矩形大小是否不超过1.5倍的平均值
        if w <= 1.5 * average_width and h <= 1.5 * average_height:
            # 在原图上画出矩形
            cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 5)

            # 提取并保存字符图像
            char_img = image[y:y + h, x:x + w]
            char_filename = os.path.join(chars_dir, f'{count}.png')
            cv2.imwrite(char_filename, char_img)
            count += 1

# 显示处理后的图像
cv2.imshow('Processed Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()